{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "979989a5",
   "metadata": {},
   "source": [
    "# Instructions:\n",
    "\n",
    "### 1 - Run the first 2 cells to declare the LabelUitls class\n",
    "### 2 - Call the method ```create_shuffled_images_folder``` to shuffle the images generated in the previous notebook and insert them in a folder called shuffled_images\n",
    "### 3 - Using the website ```makesense.ai```, label the images from the shuffled_images folder\n",
    "### 4 - After labeling the images, export the txt files with the labels from the website ```makesense.ai``` and copy the txt files into the shuffled_images folder\n",
    "### 5 - Run the method ```create_labeled_images_zip_file``` to copy the labeled images to a zip file that will be used to train the model\n",
    "### 6 - update the ```classes``` variables with the label names that you used on makesense.ai\n",
    "### 7 - run the method ```update_config_files```\n",
    "### 8 - upload the ```yolov4-tiny``` folder to the root of your google drive"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91800ec7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import random\n",
    "import shutil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4c4ac90",
   "metadata": {},
   "outputs": [],
   "source": [
    "class LabelUtils:\n",
    "\n",
    "    def create_shuffled_images_folder(self):\n",
    "        if not os.path.exists(\"shuffled_images\"):\n",
    "            os.mkdir(\"shuffled_images\")\n",
    "\n",
    "        image_files = [f for f in os.listdir(\"images\") if f.endswith(\".jpg\")]\n",
    "        random.shuffle(image_files)\n",
    "\n",
    "        for img in image_files:\n",
    "            os.rename(f\"images/{img}\", f\"shuffled_images/img_{len(os.listdir('shuffled_images'))}.jpg\")\n",
    "\n",
    "    def create_labeled_images_zip_file(self):\n",
    "        if not os.path.exists(\"obj\"):\n",
    "            os.mkdir(\"obj\")\n",
    "\n",
    "        file_prefixes = [f.split('.')[0] for f in os.listdir(\"shuffled_images\") if f.endswith(\".txt\")]\n",
    "\n",
    "        for prefix in file_prefixes:\n",
    "            os.rename(f\"shuffled_images/{prefix}.txt\", f\"obj/{prefix}.txt\")\n",
    "            os.rename(f\"shuffled_images/{prefix}.jpg\", f\"obj/{prefix}.jpg\")\n",
    "\n",
    "        shutil.make_archive('yolov4-tiny/obj', 'zip', '.', 'obj')\n",
    "\n",
    "    def update_config_files(self, classes):\n",
    "        with open(\"./yolov4-tiny/obj.names\", \"w\") as file:\n",
    "            file.write(\"\\n\".join(classes))\n",
    "\n",
    "        with open(\"./yolov4-tiny/yolov4-tiny-custom_template.cfg\", 'r') as file:\n",
    "            cfg_content = file.read()\n",
    "\n",
    "        updated_cfg_content = cfg_content.replace('_CLASS_NUMBER_', str(len(classes)))\n",
    "        updated_cfg_content = updated_cfg_content.replace('_NUMBER_OF_FILTERS_', str((len(classes) + 5) * 3))\n",
    "        updated_cfg_content = updated_cfg_content.replace('_MAX_BATCHES_', str(max(6000, len(classes) * 2000)))\n",
    "\n",
    "        with open(\"./yolov4-tiny/yolov4-tiny-custom.cfg\", 'w') as file:\n",
    "            file.write(updated_cfg_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0f917840",
   "metadata": {},
   "outputs": [],
   "source": [
    "# If you're not going to label all the generated images, make sure to shuffle them.\n",
    "# Shuffling helps ensure that you will cover a wide range of scenarios. \n",
    "# This avoids any bias towards specific patterns or sequences.\n",
    "\n",
    "# The function below shuffles the images in the images folder and inserts them into the shuffled_images folder.\n",
    "\n",
    "lbUtils = LabelUtils()\n",
    "lbUtils.create_shuffled_images_folder()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2395f8b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# After creating the dataset (and shuffling the images), the next step is to label the images. \n",
    "# (I recommend using https://www.makesense.ai/). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "614caeba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# After labeling the images, extract the content of the zip file from the makesense.ai webside and\n",
    "# copy the .txt yolo label files into the \"shuffled_images\" folder and execute the following command\n",
    "# to generate a zip file with the images and labels inside the yolov4-tiny folder.\n",
    "\n",
    "lbUtils = LabelUtils()\n",
    "lbUtils.create_labeled_images_zip_file()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b15d858f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Now, fill this list with the classes you used in the makesense.ai.\n",
    "\n",
    "# ***************************************************************************\n",
    "# Make sure that you enter the exact same classes and in the exact same order!!!\n",
    "# ***************************************************************************\n",
    "\n",
    "# if you insert a different number than was used in the makesense.ai website the model wont work!\n",
    "\n",
    "classes = [\"YOUR\", \"LABEL\", \"NAMES\"]\n",
    "\n",
    "lbUtils = LabelUtils()\n",
    "lbUtils.update_config_files(classes)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e39ea7af",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Now, add the \"yolov4-tiny\" folder to the root directory of your Google Drive\n",
    "# and proceed to train the model using the \"yolo_model_training\" \n",
    "# notebook in Google Colab.\n",
    "\n",
    "# Ensure that the \"yolov4-tiny\" folder has the following structure and files:\n",
    "\n",
    "# yolov4-tiny/\n",
    "# ├── obj.data\n",
    "# ├── obj.names\n",
    "# ├── obj.zip\n",
    "# ├── process.py\n",
    "# ├── yolov4-tiny.conv.29\n",
    "# ├── yolov4-tiny-custom.cfg\n",
    "# ├── yolov4-tiny-custom_template.cfg\n",
    "# └── training/\n",
    "#     └── placeholder.txt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b04816e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# After that, upload the 3_yolo_model_training notebook on google colab and follow its instructions there."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "315e92e4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
